package com.mes.schedule.manager.iface;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.transaction.annotation.Transactional;

import com.mes.common.exception.bo.BaseBusinessException;
import com.mes.common.manager.iface.IBasicManager;
import com.mes.common.spring.SpringUtils;
import com.mes.schedule.domain.SDevice;
import com.mes.schedule.domain.SGroupOperationTask;
import com.mes.schedule.domain.SOperationTask;
import com.mes.schedule.domain.SParallelGroup;
import com.mes.schedule.domain.SPartTask;
import com.mes.schedule.domain.STempOperationTask;
import com.mes.schedule.domain.SWorkCenter;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.task.domain.OperationTask;

/**
 * 工序任务管理 ClassName: ScheduleOperationTaskManager <br/> Function: TODO ADD
 * FUNCTION. <br/> Reason: TODO ADD REASON. <br/> date: Jun 22, 2015 9:08:57 PM
 * <br/>
 * 
 * @author Administrator
 * @version
 * @since JDK 1.6
 */
public interface IScheduleOperationTaskManager extends IBasicManager {

	public void calcAlterResourceList(SOperationTask operationTask);

	public void changeDevice(SOperationTask operationTask, SDevice device)
			throws Exception;

	public boolean useDevice(SOperationTask operationTask, SDevice device);

	public void calcControlEarlyStart(SOperationTask operationTask);

	/**
	 * 最早完成时间
	 */
	public void calcControlEarlyFinish(SOperationTask operationTask);

	public void calcControlFinish(SOperationTask operationTask);

	public void lockTask(String scheduleUid, String taskUid, Date planStart,
			Date planFinish, String deviceUid);

	public void unlockTask(String scheduleUid, String taskUid);

	public Date calcTaskPlanFinish(SOperationTask operationTask,
			Date planStart, Double estiPreTime, Double estiRunTime,
			Boolean changeOperation);

	public void cancelGroupTask(SGroupOperationTask groupTask) throws Exception;

	public void addMemberTask(SGroupOperationTask groupTask, String taskUid)
			throws Exception;

	public void deleteMemberTask(SGroupOperationTask groupTask, String taskUid)
			throws Exception;

	public void addMemberTask(SGroupOperationTask groupTask,
			SOperationTask memberTask) throws Exception;

	public void deleteMemberTask(SGroupOperationTask groupTask,
			SOperationTask memberTask) throws Exception;

	public SOperationTask groupTasks(List<SPartTask> groupPartTasks,
			String OperationIDDesc, Integer groupType) throws Exception;

	public List<SOperationTask> filter(
			Collection<SOperationTask> operationTaskList, String drawingId,
			String batchNum, Date lateFinish, Integer planGrade,
			Integer priority, String masterShop, String deptId,
			Integer coTaskState);

	/**
	 * 过滤委外任务，按照状态排序
	 * 
	 * @param scheme
	 * @param operationTaskList
	 * @param likeTask
	 * @return
	 */
	public List<SOperationTask> filterOutTask(ScheduleScheme scheme,
			Collection<SOperationTask> operationTaskList,
			SOperationTask likeTask);

	/**
	 * 过滤协作任务，按照状态排序
	 * 
	 * @param scheme
	 * @param operationTaskList
	 * @param likeTask
	 * @return
	 */
	public List<SOperationTask> filterInTask(ScheduleScheme scheme,
			Collection<SOperationTask> operationTaskList,
			SOperationTask likeTask);

	public void updateOperationTask(ScheduleScheme scheme,
			SOperationTask newTask) throws Exception;

	public void sortByPriorityTaskDistanceSlack(
			List<SOperationTask> operationTaskList);

	public boolean isReady(SOperationTask operationTask);

	public List<SOperationTask> getOperationTaskListSortByNetDepth(
			ScheduleScheme scheme, String partTaskUid) throws Exception;

	public List<SOperationTask> getOperationTaskListSortByOutLineNumber(
			ScheduleScheme scheme, String partTaskUid) throws Exception;

	public List<SOperationTask> getOperationTaskListByOutlineNumber(
			ScheduleScheme scheme, String partTaskUid, String outlineNumber)
			throws Exception;

	public List<SOperationTask> getOperationTaskList(ScheduleScheme scheme,
			String partTaskUid) throws Exception;

	public void removeOperationTask(ScheduleScheme scheme,
			String operationTaskUid) throws Exception;

	/**
	 * 根据参数isRemovedFromDB判断是否从数据库删除 hba
	 * 
	 * @param sOperationTask
	 * @param isRemovedFromDB
	 * @throws Exception
	 */
	public void removeOperationTask(SOperationTask sOperationTask,
			Boolean isRemovedFromDB) throws Exception;

	/**
	 * 仅仅将工序任务移除，不从数据库移除
	 * 
	 * @param so
	 * @throws Exception
	 */
	public void justRemoveOperationTask(SOperationTask so) throws Exception;

	// 可用于工序顺序无关组的建立
	public void parallel(List<SOperationTask> operationTaskList)
			throws Exception;

	// 可用于取消工序顺序无关组
	public void cancleParallel(SParallelGroup pallelGroup) throws Exception;

	// //添加顺序无关组任务
	// public void addParallelGroup(ScheduleScheme scheme, String partTaskUid,
	// List<SOperationTask> opList) throws Exception;

	/**
	 * 为零件任务添加工序任务 注意：返回的实体对象才是新增的对象
	 * 
	 * @param scheme
	 * @param so
	 * @param partTask
	 * @return 返回的实体对象才是新增的对象
	 * @throws Exception
	 */

	public SOperationTask addOperationTask(ScheduleScheme scheme,
			SOperationTask so, SPartTask partTask) throws Exception;

	/**
	 * 添加工序任务 注意：返回的实体对象才是新增的对象
	 * 
	 * @param <T>
	 * @param scheme
	 * @param so
	 * @return
	 * @throws Exception
	 */
	public <T extends SOperationTask> T addOperationTask(ScheduleScheme scheme,
			T so) throws Exception;

	/**
	 * add by zy 主制工段保存某一零件任务中的工序任务
	 * 
	 * @param masterScheduleUid
	 * @param dataSetOpTask
	 * @throws Exception
	 */
	public void saveMasterOperationTask(String masterScheduleUid,
			SOperationTask dataSetOpTask) throws Exception;

	/**
	 * add by zy 协作工段保存某一零件任务中的工序任务
	 * 
	 * @param coScheduleUid
	 * @param dataSetOpTask
	 * @throws Exception
	 */
	public void saveCoOperationTask(String coScheduleUid,
			SOperationTask dataSetOpTask) throws Exception;

	/**
	 * add by zy 同时保存协作与主制的工序任务
	 * 
	 * @param coScheduleUid
	 * @param dataSetOpTask
	 * @throws Exception
	 */
	public void saveMasterCoOperationTask(String masterScheduleUid,
			String coScheduleUid, SOperationTask dataSetOpTask)
			throws Exception;

	// 保存某一零件任务中的工序任务
	public void saveOperationTask(ScheduleScheme scheme, String partTaskUid,
			List<SOperationTask> opList, boolean modifyLink) throws Exception;

	// 保存一般的工序任务
	public void saveOperationTask(ScheduleScheme scheme,
			List<SOperationTask> opList) throws Exception;

	public void refreshOperationDevice(ScheduleScheme scheme, String opUid,
			SOperationTask operationTask) throws Exception;

	public void refreshOtherHour(ScheduleScheme scheme, String parentTaskUid)
			throws Exception;

	public void forceAssignToDevice(ScheduleScheme scheme, String taskUid,
			String deviceUid) throws Exception;

	public void forceNotAssignToDevice(ScheduleScheme scheme, String taskUid,
			String deviceUid) throws Exception;

	/**
	 * 清除所有设备序列
	 */
	public void clearSeq(ScheduleScheme scheme) throws Exception;

	/**
	 * 清除某一设备序列 by hba
	 */
	public void clearDeviceSeq(ScheduleScheme scheme, String deviceUid)
			throws Exception;

	/*
	 * 对派工工序任务的统一处理
	 */
	public void dispatchTask(ScheduleScheme scheme, SOperationTask operationTask)
			throws BaseBusinessException, Exception;

	/*
	 * 对取消派工工序任务的统一处理
	 */
	public void cancelDispatchTask(ScheduleScheme scheme,
			SOperationTask operationTask) throws Exception;

	/*
	 * 对派工工序任务的统一处理
	 */
	public void dispatchTask(ScheduleScheme scheme,
			SGroupOperationTask groupTask) throws Exception;

	/*
	 * 对取消派工工序任务的统一处理
	 */
	public void cancelDispatchTask(ScheduleScheme scheme,
			SGroupOperationTask groupTask) throws Exception;

	/*
	 * 对派工工序任务的统一处理
	 */
	public void dispatchTask(ScheduleScheme scheme, STempOperationTask tempTask)
			throws Exception;

	/*
	 * 对取消派工工序任务的统一处理
	 */
	public void cancelDispatchTask(ScheduleScheme scheme,
			STempOperationTask tempTask) throws Exception;

	/*
	 * 对开始工序任务的统一处理，开始进行离线生产准备
	 */
	public void startOfflinePrepare(ScheduleScheme scheme,
			SOperationTask operationTask, Date actualStart) throws Exception;

	/*
	 * 对开始工序任务的统一处理，完成离线生产准备
	 */
	public void completeOfflinePrepare(ScheduleScheme scheme,
			SOperationTask operationTask, Date actualFinish) throws Exception;

	/*
	 * 对开始工序任务的统一处理，开始进行在线准备
	 */
	public void startTask(ScheduleScheme scheme, SOperationTask operationTask,
			String deviceUid, Date actualStart) throws Exception;

	/*
	 * 对完成准备工序任务的统一处理
	 */
	public void completePrepare(ScheduleScheme scheme,
			SOperationTask operationTask, String deviceUid, Date actualFinish)
			throws Exception;

	/*
	 * 对完成首检工序任务的统一处理
	 */
	public void completeFirstCheck(ScheduleScheme scheme,
			SOperationTask operationTask, String deviceUid, Date actualFinish)
			throws Exception;

	/*
	 * 任务进度反馈
	 */
	public void feedbackTask(ScheduleScheme scheme,
			SOperationTask operationTask, Double completeQty, String deviceUid,
			Date workDate) throws Exception;

	/*
	 * 任务数量反馈
	 */
	public void feedbackQty(ScheduleScheme scheme,
			SOperationTask operationTask, Double completeQty, String deviceUid,
			Date workDate) throws Exception;

	/*
	 * 对完成工序任务的统一处理
	 */
	public void completeTask(ScheduleScheme scheme, SOperationTask operationTask)
			throws Exception;

	/*
	 * 对中断工序任务的统一处理，临时问题处理，主轴不表
	 */
	public void pauseTask(ScheduleScheme scheme, SOperationTask operationTask,
			String pauseReason, Date pauseDate, Date planResumeDate)
			throws Exception;

	/*
	 * 对中断工序任务的恢复处理,，可暂时切换到其它工作台进行操作
	 */
	public void resumeTask(ScheduleScheme scheme, SOperationTask operationTask,
			String resumeReason, Date resumeDate) throws Exception;

	/*
	 * 对中止工序任务的统一处理
	 */
	public void interruptTask(ScheduleScheme scheme,
			SOperationTask operationTask, String interruptReason,
			Date interruptDate, Date planRestartDate) throws Exception;

	/*
	 * 对中止工序任务的恢复处理
	 */
	public void restartTask(ScheduleScheme scheme,
			SOperationTask operationTask, String restartReason, Date restartDate)
			throws Exception;

	/*
	 * 改变任务状态
	 */
	public void changeTaskState(ScheduleScheme scheme,
			SOperationTask operationTask, int taskState, String changeReason,
			Date changeDate) throws Exception;

	/*
	 * @deprecated 替换工作中心 todo 暂时调度中还没有工作中心对象,所以这个方法建议不用
	 * 
	 */
	public void replaceWorkCenter(ScheduleScheme scheme,
			SOperationTask operationTask, String workCenterUid,
			String workCenterName) throws Exception;

	/*
	 * 新增报废记录
	 * 
	 */
	public void updateRejectQty(ScheduleScheme scheme,
			SOperationTask operationTask, double rejectQty) throws Exception;

	public void calTaskDistance(SPartTask partTask) throws Exception;

	public int calAssnPriority(SOperationTask operationTask, String deviceUid);

	public double calPercentComplete(SOperationTask operationTask);

	// 计算首件加工时间
	public Date calFirstCheckStart(SOperationTask operationTask);

	/*
	 * 按工时拆分工序任务，主要用于多工作台
	 */
	public void splitTask(SOperationTask operationTask, List<Double> part)
			throws Exception;

	/*
	 * 合并工序任务
	 */
	public void mergeTask(List<SOperationTask> subOperationTaskList)
			throws Exception;

	/*
	 * 取得合并工序的子任务
	 */
	public List<SOperationTask> getMemberTaskList(String scheduleUid,
			String groupTaskUid) throws Exception;

	/*
	 * 发布协作任务
	 */
	public void publishCoTask(String scheduleUid, String taskUid)
			throws Exception;

	/**
	 * 自动发布协作任务
	 * 
	 * @param scheduleUid
	 * @param taskUid
	 * @throws Exception
	 */
	public void autoPublishCoTask(ScheduleScheme scheme) throws Exception;

	/*
	 * 取消协作任务
	 */
	public void unPublishCoTask(String scheduleUid, String taskUid)
			throws Exception;

	/*
	 * 接受协作任务
	 */
	public void receiveCoTask(String scheduleUid, String taskUid)
			throws Exception;

	/*
	 * 反馈协作任务安排
	 */
	public void feedbackCoTask(String scheduleUid, String taskUid)
			throws Exception;

	/*
	 * 输出周计划时自动反馈协作任务安排，在周计划开始和结束时间内的任务需要锁定，之外的则不需锁定只需给出最早开始时间
	 */
	public void autoFeedbackCoTask(String scheduleUid, String taskUid,
			Date startDate, Date finishDate) throws Exception;

	/*
	 * 拒绝协作任务
	 */
	public void refuseCoTask(String scheduleUid, String taskUid)
			throws Exception;

	void refreshSlackAndColor(ScheduleScheme scheme,
			Collection<? extends SOperationTask> operationTasks)
			throws Exception;

	/*
	 * 工序成组
	 */
	public SOperationTask groupTasks(List<SOperationTask> memberTasks,
			Integer groupType) throws Exception;

	/*
	 * 是否可以变动设备
	 */
	public boolean canChangeDevice(SOperationTask operationTask);

	// 选择零件任务是否进入调度
	public void intoSchedule(List<SOperationTask> operationTaskList)
			throws Exception;

	public void intoSchedule(SOperationTask operationTask) throws Exception;

	public void outSchedule(List<SOperationTask> operationTaskList,
			Boolean isWaiting) throws Exception;

	public void outSchedule(SOperationTask operationTask, Boolean isWaiting)
			throws Exception;

	public OperationTask getOOTask(SOperationTask operationTask) throws Exception;

	public Set<OperationTask> getOOTasks(SOperationTask operationTask) throws Exception;

	/**
	 * 计算工作中心在某一时间之前的必须要做的任务 由里程碑，零件交货期等决定 或者松弛率小于 工序距离小于maxTaskInstance
	 */
	public List<SOperationTask> getMustDoList(SWorkCenter workCenter,Date analyseStart,
			Date analyseFinish, Double slackFactor, String drawingId,
			Integer maxTaskInstance);

	/**
	 * 初始化一个调度中的工序任务
	 * 
	 * @param scheme
	 * @param operationTask
	 */
	public void init(ScheduleScheme scheme, SOperationTask operationTask);

	/**
	 * 取得能加工的设备 建立在calResourceList之上
	 */
	public List<SDevice> getCanDoDevices(SOperationTask operationTask);

	/**
	 * 是否能够并行加工
	 * 
	 * @param operationTask
	 */
	public boolean canParallelDo(SOperationTask operationTask);

	/**
	 * 获取导致该任务发生延迟的任务列表
	 */
	public List<SOperationTask> getAffectTaskList(ScheduleScheme scheme,
			String taskUid);

	/**
	 * 取消生产准备任务
	 * 
	 * @param so
	 * @throws Exception
	 */
	public void cancelPrepareTask(SOperationTask so, Set<OperationTask> ooSet)
			throws Exception;

	/**
	 * 保存或者更新生产准备任务
	 * 
	 * @param so
	 * @throws Exception
	 */
	public void saveOrUpdatePrepareTask(SOperationTask so,
			Set<OperationTask> ooSet) throws Exception;

	public Set<SOperationTask> getAllPredOperationTasks(
			SOperationTask operationTask, SPartTask partTask);

	/**
	 * 计算工序任务的工艺上的最早开始时间 同时里面蕴含了一个逻辑，平顺， 所以这个方法应该提前进行计算，非常重要
	 * 主要是为了在不考虑设备虚拟链接情况下计算工序的等待时间
	 * 
	 * @param operationTask
	 * @return
	 */
	public Date getRealControlEarlyStart(SOperationTask operationTask);

	/**
	 * 计算工序任务的工艺上的最早完成时间 与计算controlEarlyFinish最大的区别是为了在不考虑设备虚拟链接情况下计算工序的等待时间
	 * 主要是为了方便统计工序上的等待时间
	 * 
	 * @param operationTask
	 * @return
	 */
	public Date getRealControlEarlyFinish(SOperationTask operationTask);

	/**
	 * 取消一台设备上所有的任务分派
	 * 
	 * @param scheme
	 * @param device
	 * @throws Exception
	 */
	public void cancelAllDispatch(ScheduleScheme scheme, SDevice device)
			throws Exception;

	/**
	 * 更新工序任务增删改后对工序链接造成的影响
	 * 
	 * @param modifyLink
	 * @param newOp
	 * @param partTask
	 * @throws Exception
	 */
	public void updateScheduleLink(boolean modifyLink, SOperationTask newOp,
			SPartTask partTask) throws Exception;

	/**
	 * 初始化代派工工序任务，用于手动排产 by hba
	 * 
	 * @param scheme
	 * @param resUid
	 * @return
	 */
	public List<SOperationTask> initDispatchTask(ScheduleScheme scheme,
			String resUid);

	/**
	 * 初始化已派工工序任务，用于展示在fullCalendar控件上 by hba
	 * 
	 * @param scheme
	 * @return
	 */
	public List<SOperationTask> initDispatchedTask(ScheduleScheme scheme);

	/**
	 * 获取任务日历视图中待派的任务树
	 * 
	 * @param scheme
	 * @param taskUid
	 * @return
	 */
	public List<SOperationTask> initDispatchTaskByTaskUid(
			ScheduleScheme scheme, String taskUid);

	/**
	 * 获取任务日历视图中已派的任务树 hba
	 * 
	 * @param scheme
	 * @param taskUid
	 * @return
	 */
	public List<SOperationTask> initDispatchedTaskByTaskUid(
			ScheduleScheme scheme, String taskUid);

	/**
	 * 初始化任务日历视图中的就绪任务集合 即taskUid对应的零件任务的首工序 如果taskUid为空，则取所有零件的第一道工序
	 * 
	 * @param scheme
	 * @param taskUid
	 * @return
	 */
	public List<SOperationTask> initDispatchReadyTaskByTaskUid(
			ScheduleScheme scheme, String taskUid);

	/**
	 * 初始化资源日历视图中的已派任务集合 过滤分派在resUid对应设备上的任务
	 * 
	 * @param scheme
	 * @param resUid
	 * @return
	 */
	public List<SOperationTask> initDispatchedTaskByResUid(
			ScheduleScheme scheme, String resUid);

	/**
	 * 创建资源视图中准备就绪的未派的主制工序
	 * 
	 * @param scheme
	 * @param resUid
	 * @param taskDistance
	 * @return
	 */
	public List<SOperationTask> initDispatchReadyTaskByResUid(
			ScheduleScheme scheme, String resUid, int taskDistance);

	/**
	 * 按照工序距离初始化就绪班产任务
	 * 
	 * @param scheme
	 * @param resUid
	 * @param taskDistance
	 * @return
	 */
	public List<SOperationTask> initDispatchReadyTaskBCByResUid(
			ScheduleScheme scheme, String resUid, int taskDistance);

	/**
	 * 获取资源日历视图中下一道工序，该工序需要是未派的，能在resUid加工的
	 * 
	 * @param scheme
	 * @param operationTask
	 * @param resUid
	 * @return
	 */
	public List<SOperationTask> initDispatchNextTask(ScheduleScheme scheme,
			SOperationTask operationTask, String resUid);

	/**
	 * 过滤该设备上所有的工序任务
	 * 
	 * @param scheme
	 * @param resUid
	 * @return
	 */
	public List<SOperationTask> initDispatchedAllTaskByResUid(
			ScheduleScheme scheme, String resUid);

	/**
	 * 初始化设备上所有的任务
	 * 
	 * @param scheme
	 * @param taskUid
	 * @return
	 */
	public List<SOperationTask> initAllDispatchedTaskByTaskUid(
			ScheduleScheme scheme, String taskUid);

	public List<SOperationTask> initPartTaskByTaskUid(ScheduleScheme scheme,
			String taskUid, String allPartTask, String isCriticalOp,
			String allTask);

	/**
	 * 获取班产视图关注的工序 hba
	 * 
	 * @param scheme
	 * @param taskUid
	 * @throws Exception
	 */
	public List<SOperationTask> getOperationTaskListForShiftProduction(
			ScheduleScheme scheme, String taskUid) throws Exception;

	/**
	 * 获取手动安排的工序任务 hba
	 * 
	 * @param scheduleUid
	 * @return
	 */
	public List<SOperationTask> getDragedOperationTask(String scheduleUid)
			throws Exception;

}
